package core

import (
    "sdl"
)

type FPSTimer struct {
    fps         uint32
    fpsWait     uint32
    fpsWaitTT   uint32
    lastDraw    uint32
    elapsedTime uint32
    unuseSleep  uint32
    drawTime    [32]uint32
    elapseTime  [32]uint32
    drawCount   int
    callCount   int

    frameSkip         bool
    frameSkipCounter  int
    frameSkipCounterN int
}

func (f *FPSTimer) SetFPS(fps uint32) {
	f.ResetTimer()
	f.ResetElapseTimeCounter()

	f.callCount = 0
	f.unuseSleep = 0
	f.drawCount = 0

	f.fps = fps
	if fps == 0 {
		return
	}

	// １フレームごとに何us待つ必要があるのか？
	f.fpsWait = (uint32)((1000*0x10000) / fps)
	f.fpsWaitTT = 0
}

func (f *FPSTimer) ResetTimer() {
	f.lastDraw = sdl.GetTicks() // 前回描画時間は、ここで設定
	f.frameSkip = false
	f.frameSkipCounter = 0
	f.frameSkipCounterN = 0
}

func (f *FPSTimer) ResetElapseTimeCounter() {
	f.elapsedTime = 0
}

func (f *FPSTimer) ResetCallCounter() {
	f.callCount = 0
}

func (f *FPSTimer) WaitFrame() {
	var t uint32 = sdl.GetTicks()

	if f.fps != 0 && (f.callCount % (int)(f.fps) == 0) {
		f.frameSkipCounter = f.frameSkipCounterN
		f.frameSkipCounterN = 0
	}

	f.drawTime[(int)(f.drawCount & 31)] = t
	f.drawCount++
	if f.drawCount == 64 { f.drawCount = 32 }

	f.callCount++

	if f.fps == 0 {
		f.elapseTime[(int)(f.drawCount & 31)] = 0
		return
	}

	f.fpsWaitTT = (f.fpsWaitTT & 0xffff) + f.fpsWait
	var wait uint32 = f.fpsWaitTT >> 16

	var elp uint32 = (uint32)(t - f.lastDraw)
	if elp >= wait {
		var delay uint32 = elp - wait;

		if delay >= 250 {
			delay = 0
		}

		f.frameSkip = (delay >= wait * 3)
		if f.frameSkip { f.frameSkipCounterN++ }

		if delay < 250 { t -= delay } else { t -= 250 }

		f.lastDraw = t
		f.elapseTime[(int)(f.drawCount & 31)] = 0
		return
	}

	f.elapsedTime += elp
	f.elapseTime[(int)(f.drawCount & 31)] = elp

	f.frameSkip = false

	sdl.Delay(wait - elp)

	f.lastDraw += wait
}

func (f *FPSTimer) ToBeSkip() bool {
	return f.frameSkip
}

func (f *FPSTimer) GetRealFPS() uint32 {
	if f.drawCount < 16 { return 0 }

	if f.drawCount < 32 {
		var t uint32 = f.drawTime[(int)(f.drawCount - 1)] - f.drawTime[(int)(f.drawCount - 16)]
		if t == 0 {
			return 0
		}
		return (uint32)((1000 * 15 + t / 2) / t)
	}

	var t uint32 = f.drawTime[(int)(f.drawCount - 1) & 31] - f.drawTime[(int)(f.drawCount & 31)]
	if t == 0 {
		return 0
	}
	return (uint32)((1000 * 31 + t / 2) / t)
}

